﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Objects;
using System.Globalization;
using System.Linq;
using EstateNuke.Data.Properties;

namespace EstateNuke.Data
{
    public partial class LeaseOrder
    {
        #region Fileds & Properties

        /// <summary>
        /// </summary>
        internal IList<LeaseOrderFacility> LeaseOrderFacilities
        {
            get
            {
                return InternalLeaseOrderFacilities.Where(leaseOrderFacility => leaseOrderFacility.IsDeleted == false).ToList();
            }
        }

        /// <summary>
        /// </summary>
        public IDictionary<Facility, string> FacilityRequirements
        {
            get
            {
                return InternalLeaseOrderFacilities.Where(leaseOrderFacility => leaseOrderFacility.IsDeleted == false && leaseOrderFacility.Facility.IsDeleted == false).ToDictionary(leaseOrderFacility => leaseOrderFacility.Facility, leaseOrderFacility => leaseOrderFacility.Requirement);
            }
        }

        /// <summary>
        /// </summary>
        public LeaseOrderEngagedContractAlert LatestUnProcessedLeaseOrderEngagedContractAlert
        {
            get
            {
                return InternalLeaseOrderEngagedContractAlerts.FirstOrDefault(leaseOrderEngagedContractAlert => leaseOrderEngagedContractAlert.IsDeleted == false && leaseOrderEngagedContractAlert.Processed == false);
            }
        }

        /// <summary>
        /// </summary>
        public IList<LeaseOrderEngagedContractAlert> LeaseOrderEngagedContractAlerts
        {
            get
            {
                return InternalLeaseOrderEngagedContractAlerts.Where(leaseOrderEngagedContractAlert => leaseOrderEngagedContractAlert.IsDeleted == false).ToList();
            }
        }

        #endregion

        #region Add & Remove LeaseOrderFacility

        /// <summary>
        /// </summary>
        /// <returns></returns>
        internal LeaseOrderFacility AddLeaseOrderFacility(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var leaseOrderFacility = new LeaseOrderFacility
                                         {
                                             RowId = Guid.NewGuid(),
                                             CreatedDate = DateTime.Now,
                                         };
            InternalLeaseOrderFacilities.Add(leaseOrderFacility);
            leaseOrderFacility.IsDeleted = false;
            leaseOrderFacility.ModifiedDate = DateTime.Now;
            leaseOrderFacility.ModifiedByUser = modifiedUser;
            return leaseOrderFacility;
        }

        /// <summary>
        /// </summary>
        /// <param name = "leaseOrderFacility"></param>
        /// <param name = "modifiedUser"></param>
        internal void RemoveLeaseOrderFacility(LeaseOrderFacility leaseOrderFacility, User modifiedUser)
        {
            if (leaseOrderFacility == null)
            {
                throw new ArgumentNullException("leaseOrderFacility");
            }
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (InternalLeaseOrderFacilities.Contains(leaseOrderFacility))
            {
                leaseOrderFacility.Delete(modifiedUser);
            }
        }

        #endregion

        #region Set FacilityRequirements

        /// <summary>
        /// </summary>
        /// <param name = "facilityRequirements"></param>
        /// <param name = "modifiedUser"></param>
        public void SetFacilityRequirements(IDictionary<Facility, string> facilityRequirements, User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (facilityRequirements != null)
            {
                var leaseOrderFacilities = InternalLeaseOrderFacilities.ToList();
                leaseOrderFacilities.ForEach(leaseOrderFacility => leaseOrderFacility.Delete(modifiedUser));
                foreach (var facilityRequirement in facilityRequirements)
                {
                    var currentLeaseOrderFacility = leaseOrderFacilities.FirstOrDefault(leaseOrderFacility => leaseOrderFacility.Facility == facilityRequirement.Key);
                    if (currentLeaseOrderFacility != null)
                    {
                        currentLeaseOrderFacility.CancelDelete(modifiedUser);
                        currentLeaseOrderFacility.Requirement = facilityRequirement.Value;
                    }
                    else
                    {
                        currentLeaseOrderFacility = AddLeaseOrderFacility(modifiedUser);
                        currentLeaseOrderFacility.Facility = facilityRequirement.Key;
                        currentLeaseOrderFacility.Requirement = facilityRequirement.Value;
                    }
                }
            }
        }

        #endregion

        #region Create & Remove LeaseOrderEngagedContractAlert

        /// <summary>
        /// </summary>
        /// <param name = "alertType"></param>
        /// <param name = "modifiedUser"></param>
        public LeaseOrderEngagedContractAlert CreateLeaseOrderEngagedContractAlert(AlertType alertType, User modifiedUser)
        {
            if (alertType == null)
            {
                throw new ArgumentNullException("alertType");
            }
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (alertType.Id != 100)
            {
                throw new ArgumentException("alertType");
            }
            if (!LeaseAgreementReference.IsLoaded)
            {
                LeaseAgreementReference.Load(MergeOption.PreserveChanges);
            }
            var reminderDays = alertType.DefaultReminderDays.HasValue ? alertType.DefaultReminderDays : 0;
            var alertTypeReminderDays = LeaseAgreement.Project.AlertTypeReminderDays;
            if (alertTypeReminderDays != null && alertTypeReminderDays.ContainsKey(alertType) && alertTypeReminderDays[alertType] != null && alertTypeReminderDays[alertType].Item1.HasValue)
            {
                reminderDays = alertTypeReminderDays[alertType].Item1;
            }
            if (reminderDays != 0)
            {
                var leaseOrderEngagedContractAlert = InternalLeaseOrderEngagedContractAlerts.FirstOrDefault(item => item.IsDeleted == false && item.Processed == false);
                if (leaseOrderEngagedContractAlert == null)
                {
                    leaseOrderEngagedContractAlert = new LeaseOrderEngagedContractAlert
                                                         {
                                                             RowId = Guid.NewGuid(),
                                                             CreatedDate = DateTime.Now,
                                                         };
                    InternalLeaseOrderEngagedContractAlerts.Add(leaseOrderEngagedContractAlert);
                }
                leaseOrderEngagedContractAlert.IsDeleted = false;
                leaseOrderEngagedContractAlert.ModifiedDate = DateTime.Now;
                leaseOrderEngagedContractAlert.ModifiedByUser = modifiedUser;
                leaseOrderEngagedContractAlert.AlertType = alertType;
                leaseOrderEngagedContractAlert.RemindDate = EngagedContractDate.AddDays((double) reminderDays);
                return leaseOrderEngagedContractAlert;
            }
            return null;
        }

        /// <summary>
        /// </summary>
        /// <param name = "leaseOrderEngagedContractAlert"></param>
        /// <param name = "modifiedUser"></param>
        public void RemoveLeaseOrderEngagedContractAlert(LeaseOrderEngagedContractAlert leaseOrderEngagedContractAlert, User modifiedUser)
        {
            if (leaseOrderEngagedContractAlert == null)
            {
                throw new ArgumentNullException("leaseOrderEngagedContractAlert");
            }
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (InternalLeaseOrderEngagedContractAlerts.Contains(leaseOrderEngagedContractAlert))
            {
                leaseOrderEngagedContractAlert.Delete(modifiedUser);
            }
        }

        #endregion

        #region Ensure

        /// <summary>
        /// </summary>
        public void Ensure()
        {
            if (string.IsNullOrEmpty(OrderNumber))
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture, Resources.NotNullAllowed, RowId, "LeaseOrder", "OrderNumber"));
            }
            if (ReducedUnitPricePerMonth < 0)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture, Resources.NonNegativeNumberAllowed, RowId, "LeaseOrder", "ReducedUnitPricePerMonth"));
            }
            if (ReducedTotalPricePerMonth < 0)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture, Resources.NonNegativeNumberAllowed, RowId, "LeaseOrder", "ReducedTotalPricePerMonth"));
            }
            if (LeaseMonths < 0)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture, Resources.NonNegativeNumberAllowed, RowId, "LeaseOrder", "LeaseMonths"));
            }
            if (TotalAmount < 0)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture, Resources.NonNegativeNumberAllowed, RowId, "LeaseOrder", "TotalAmount"));
            }
            if (DepositAmount < 0)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture, Resources.NonNegativeNumberAllowed, RowId, "LeaseOrder", "DepositAmount"));
            }
            if (GuarantyAmount < 0)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture, Resources.NonNegativeNumberAllowed, RowId, "LeaseOrder", "GuarantyAmount"));
            }
            if (OtherAmount < 0)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture, Resources.NonNegativeNumberAllowed, RowId, "LeaseOrder", "OtherAmount"));
            }
            OrderNumber = OrderNumber.Length > 32 ? OrderNumber.Substring(0, 32) : OrderNumber;
            EngagedContractDate = EngagedContractDate.Date;
            Comment = string.IsNullOrEmpty(Comment) ? null : Comment.Length > 512 ? Comment.Substring(0, 512) : Comment;
        }

        #endregion

        #region Delete

        /// <summary>
        /// </summary>
        public void Delete(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            IsDeleted = true;
            ModifiedDate = DateTime.Now;
            ModifiedByUser = modifiedUser;
            ((List<LeaseOrderFacility>) LeaseOrderFacilities).ForEach(leaseOrderFacility => leaseOrderFacility.Delete(modifiedUser));
            ((List<LeaseOrderEngagedContractAlert>) LeaseOrderEngagedContractAlerts).ForEach(leaseOrderEngagedContractAlert => leaseOrderEngagedContractAlert.Delete(modifiedUser));
        }

        /// <summary>
        /// </summary>
        public void CancelDelete(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            IsDeleted = false;
            ModifiedDate = DateTime.Now;
            ModifiedByUser = modifiedUser;
        }

        #endregion
    }
}